package com.bit.cfdi.web.domain;

import static javax.persistence.GenerationType.IDENTITY;

import java.io.Serializable;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;

@Entity
@Table(name = "comprobante")
public class Comprobante implements Serializable {

	private static final long serialVersionUID = 1L;
	
	//CONSTANTES DE FORMA DE PAGO
    //public final static String FORMA_PAGO_UNA_SOLA_EXIBICION = "Pago en una sola exhibici\u00F3n";
   // public final static String FORMA_PAGO_PARCIALIDADES = "Parcialidad x de y";
	
	public static final int ESTADO_FACTURA_CANCELADA = 0;
	public static final int ESTADO_FACTURA_ACTIVA = 1;
	public static final int ESTADO_FACTURA_BORRADOR = 2;
	public static final int ESTADO_FACTURA_BORRADA = 3;
	public static final int ESTADO_FACTURA_SIN_TIMBRAR = 4;
	
	public static final String CATEGORIA_FACTURA = "factura";
	public static final String CATEGORIA_NOTA = "nota";
	public static final String CATEGORIA_NOTA_CREDITO = "nota de credito";
	public static final String CATEGORIA_RECIBO = "recibo";
	public static final String CATEGORIA_RECIBO_DONATARIA = "recibo donataria";
	public static final String CATEGORIA_CARTA_PORTE = "carta porte";
	
	public static final String TIPO_COMP_TRASLADO = "traslado";
	public static final String TIPO_COMP_INGRESO = "ingreso";
	public static final String TIPO_COMP_EGRESO = "egreso";
	
	public static final int CALCULO_PERSONALIZADO = 1;
	public static final int CALCULO_NORMAL = 0;
	
	//public static final int COMPROBANTE_LIQUIDADO = 0;
	//public static final int COMPROBANTE_PENDIENTE = 1;
	// Fields

	private Long idComprobante;
	private String idExterno;
	private Negocio negocio;
	private Cliente cliente;
	private Integer estatus;
	private Byte [] comprobanteXml;
	private String uuid;
	private Calendar fechaTimbrado;
	private String rfcReceptor;
	private Calendar fechaCreacion;
	private MetodoPago metodoPago;
	private Integer parcialidades;
	private Double montoParcialidades;	
	private Double descuentoGeneral;
	private Double total;
	private Long ultimaModificacionPor;
	private Calendar fechaModificacion;
	private String tipoComprobante;
	private Double subTotal;
	private String moneda;
	private Double tipoDeCambio;
	private String folio;
	private String serie;
	private String categoriaComprobante;
	private Byte [] comprobanteXmlCancelado;
	//private String pathXML;
	private Byte [] pdf;
	private ComprobanteCredito comprobanteCredito;
	private FormaPago formaPago;
	private Integer numeroParcialidad;
	private Integer anhoAprobacion;
	private String noAprobacion;	
	private String motivoDescuento;
	private String lugarExpedicion;
	private String numeroCuentaPago;
	private Double version;
	private Comprobante comprobantePadre;
	private Integer calculo;
	private Set<DesgloseImpuesto> desgloseImpuestos = 
		new HashSet<DesgloseImpuesto>(0);
	private Set<OrdenCompra> ordenCompra = 
			new HashSet<OrdenCompra>(0);
	private Set<PagoParcialidad> pagosParcialidades = 
		new HashSet<PagoParcialidad>(0);
	private Set<ComprobanteConcepto> comprobanteConceptos = 
		new HashSet<ComprobanteConcepto>(0);
	private Set<ValorCampoExtraComprobante> comprobanteCamposExtra =
		new HashSet<ValorCampoExtraComprobante>(0);/*
	private Set<ComprobanteEtiqueta> comprobanteEtiquetas = 
		new HashSet<ComprobanteEtiqueta>(0);
	private Set<ComprobanteFirma> comprobanteFirmas = 
		new HashSet<ComprobanteFirma>(0);*/
	private Set<ComprobanteDescuento> comprobanteDescuento = 
		new HashSet<ComprobanteDescuento>(0);/*
	private Set<ComprobanteLeyenda> comprobanteLeyenda = 
		new HashSet<ComprobanteLeyenda>(0);*/
	private Set<Comprobante> comprobantesHijos =
		new HashSet<Comprobante>(0);
	private CartaPorte cartaPorte;
	private Calendar fechaCancelacion;
	//private Personalizacion personalizacion;
	private Donataria donataria;

	// Property accessors
	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "id_comprobante", nullable = false)
	public Long getIdComprobante() {
		return this.idComprobante;
	}

	public void setIdComprobante(Long idComprobante) {
		this.idComprobante = idComprobante;
	}
	
	@Column(name = "id_externo")
	public String getIdExterno() {
		return idExterno;
	}
	
	/**
	 * Este Id es para uso exclusivo del BridgeTXT para guardar el nombre del
	 * archivo que ya fue procesado.
	 * @param idExterno
	 */
	public void setIdExterno(final String idExterno) {
		this.idExterno = idExterno;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "id_negocio")
	public Negocio getNegocio() {
		return this.negocio;
	}

	public void setNegocio(Negocio negocio) {
		this.negocio = negocio;
	}

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "id_cliente")
	public Cliente getCliente() {
		return this.cliente;
	}

	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}
	
	@OneToOne
	@JoinColumn(name = "id_comprobante_credito")
	public ComprobanteCredito getComprobanteCredito() {
		return comprobanteCredito;
	}
	
	public void setComprobanteCredito(ComprobanteCredito comprobanteCredito) {
		this.comprobanteCredito = comprobanteCredito;
	}

	@Column(name = "estatus")
	public Integer getEstatus() {
		return this.estatus;
	}

	public void setEstatus(Integer estatus) {
		this.estatus = estatus;
	}

	@Lob
	@Column(name = "comprobante_xml", nullable = false, columnDefinition="longblob")
	public Byte[] getComprobanteXml() {
		return this.comprobanteXml;
	}

	public void setComprobanteXml(Byte[] comprobanteXml) {
		this.comprobanteXml = comprobanteXml;
	}

	@Column(name = "UUID", length = 100)
	public String getUuid() {
		return this.uuid;
	}

	public void setUuid(String uuid) {
		this.uuid = uuid;
	}

	@Column(name = "fecha_timbrado")
	@Temporal(TemporalType.TIMESTAMP)
	public Calendar getFechaTimbrado() {
		return this.fechaTimbrado;
	}

	public void setFechaTimbrado(Calendar fechaTimbrado) {
		this.fechaTimbrado = fechaTimbrado;
	}

	@Column(name = "rfc_receptor", length = 13)
	public String getRfcReceptor() {
		return this.rfcReceptor;
	}

	public void setRfcReceptor(String rfcReceptor) {
		this.rfcReceptor = rfcReceptor;
	}

	@Column(name = "fecha_creacion")
	@Temporal(TemporalType.TIMESTAMP)
	public Calendar getFechaCreacion() {
		return this.fechaCreacion;
	}

	public void setFechaCreacion(Calendar fechaCreacion) {
		this.fechaCreacion = fechaCreacion;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "id_metodo_pago")
	public MetodoPago getMetodoPago() {
		return this.metodoPago;
	}
	
	/**Efectivo, T Cr\u00E9dito, etc*/
	public void setMetodoPago(MetodoPago metodoPago) {
		this.metodoPago = metodoPago;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "id_forma_pago")
	public FormaPago getFormaPago() {
		return this.formaPago;
	}	
	
	public void setFormaPago(FormaPago formaPago) {
		this.formaPago = formaPago;
	}

	@Column(name = "parcialidades")
	public Integer getParcialidades() {
		return this.parcialidades;
	}

	public void setParcialidades(Integer parcialidades) {
		this.parcialidades = parcialidades;
	}
	
	@Column(name = "descuento_general", precision = 52, scale = 6)
	public Double getDescuentoGeneral() {
		return this.descuentoGeneral;
	}
	
	public void setDescuentoGeneral(Double descuentoGeneral) {
		this.descuentoGeneral = descuentoGeneral;
	}
	
	@Column(name = "monto_parcialidades", precision = 52, scale = 6)
	public Double getMontoParcialidades() {
		return this.montoParcialidades;
	}

	/***/
	public void setMontoParcialidades(Double montoParcialidades) {
		this.montoParcialidades = montoParcialidades;
	}
	
	@Column(name = "total", precision = 52, scale = 6)
	public Double getTotal() {
		return this.total;
	}

	public void setTotal(Double total) {
		this.total = total;
	}
	
	@Column(name = "tipo_comprobante", length = 150)
	public String getTipoComprobante() {
		return tipoComprobante;
	}

	public void setTipoComprobante(String tipoComprobante) {
		this.tipoComprobante = tipoComprobante;
	}

	@Column(name = "subtotal", precision = 52, scale = 6)
	public Double getSubTotal() {
		return subTotal;
	}

	public void setSubTotal(Double subTotal) {
		this.subTotal = subTotal;
	}

	@Column(name = "moneda", length = 40)
	public String getMoneda() {
		return moneda;
	}

	public void setMoneda(String moneda) {
		this.moneda = moneda;
	}

	@Column(name = "tipo_de_cambio")
	public Double getTipoDeCambio() {
		return tipoDeCambio;
	}

	public void setTipoDeCambio(Double tipoDeCambio) {
		this.tipoDeCambio = tipoDeCambio;
	}
	
	@Column(name = "folio", length = 20)
	public String getFolio() {
		return folio;
	}

	public void setFolio(String folio) {
		this.folio = folio;
	}
	
	@Column(name = "serie", length = 25)
	public String getSerie() {
		return serie;
	}

	public void setSerie(String serie) {
		this.serie = serie;
	}
	
	@Column(name = "categoria_comprobante", length = 50)
	public String getCategoriaComprobante() {
		return categoriaComprobante;
	}
	
	public void setCategoriaComprobante(String categoriaComprobante) {
		this.categoriaComprobante = categoriaComprobante;
	}

	@Column(name = "ultima_modificacion_por")
	public Long getUltimaModificacionPor() {
		return this.ultimaModificacionPor;
	}
	
	public void setUltimaModificacionPor(Long ultimaModificacionPor) {
		this.ultimaModificacionPor = ultimaModificacionPor;
	}
	
	@Lob
	@Column(name = "comprobante_xml_cancelado", nullable = true, columnDefinition="longblob")
	public Byte[] getComprobanteXmlCancelado() {
		return this.comprobanteXmlCancelado;
	}

	public void setComprobanteXmlCancelado(Byte[] comprobanteXmlCancelado) {
		this.comprobanteXmlCancelado = comprobanteXmlCancelado;
	}
	
	@Column(name = "pdf", nullable = true, columnDefinition="longblob")
	public Byte[] getPathPDF() {
		return this.pdf;
	}
	
	public void setPathPDF(Byte[] pdf) {
		this.pdf = pdf;
	}

	@Column(name = "numero_parcialidad")
	public Integer getNumeroParcialidad() {
		return this.numeroParcialidad;
	}

	public void setNumeroParcialidad(Integer numeroParcialidad) {
		this.numeroParcialidad = numeroParcialidad;
	}

	@Column(name = "anho_aprobacion")
	public Integer getAnhoAprobacion() {
		return this.anhoAprobacion;
	}
	
	public void setAnhoAprobacion(Integer anhoAprobacion) {
		this.anhoAprobacion = anhoAprobacion;
	}
	
	@Column(name="no_aprobacion", length = 20)
	public String getNoAprobacion() {
		return this.noAprobacion;
	}
	
	
	public void setNoAprobacion(String noAprobacion) {
		this.noAprobacion = noAprobacion;
	}
	
	@Column(name="motivo_descuento", columnDefinition = "mediumtext")	
	public String getMotivoDescuento() {
		return this.motivoDescuento;
	}
	
	public void setMotivoDescuento(String motivoDescuento) {
		this.motivoDescuento = motivoDescuento;
	}
	
	@Column(name="lugar_expedicion", columnDefinition = "mediumtext")
	public String getLugarExpedicion() {
		return this.lugarExpedicion;
	}

	public void  setLugarExpedicion(String lugarExpedicion) {
		this.lugarExpedicion = lugarExpedicion;
	}
	
	@Column(name="version")
	public Double getVersion() {
		return this.version;
	}
	
	public void setVersion(Double version) {
		this.version = version;
	}

	@Column(name = "fecha_modificacion")
	@Temporal(TemporalType.TIMESTAMP)
	@Version
	public Calendar getFechaModificacion() {
		return this.fechaModificacion;
	}

	public void setFechaModificacion(Calendar fechaModificacion) {
		this.fechaModificacion = fechaModificacion;
	}
	
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "id_comprobante_padre")
	public Comprobante getComprobantePadre() {
		return comprobantePadre;
	}

	public void setComprobantePadre(Comprobante comprobantePadre) {
		this.comprobantePadre = comprobantePadre;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<DesgloseImpuesto> getDesgloseImpuestos() {
		return this.desgloseImpuestos;
	}

	public void setDesgloseImpuestos(Set<DesgloseImpuesto> desgloseImpuestos) {
		this.desgloseImpuestos = desgloseImpuestos;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<OrdenCompra> getOrdenCompra() {
		return this.ordenCompra;
	}

	public void setOrdenCompra(Set<OrdenCompra> ordenCompra) {
		this.ordenCompra = ordenCompra;
	}
	
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<PagoParcialidad> getPagosParcialidades() {
		return this.pagosParcialidades;
	}

	public void setPagosParcialidades(Set<PagoParcialidad> pagosParcialidades) {
		this.pagosParcialidades = pagosParcialidades;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<ComprobanteConcepto> getComprobanteConceptos() {
		return this.comprobanteConceptos;
	}

	public void setComprobanteConceptos(
			Set<ComprobanteConcepto> comprobanteConceptos) {
		this.comprobanteConceptos = comprobanteConceptos;
	}
	
	/*
	 * @deprecated
	 *
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<PedimentoAduanal> getPedimentosAduanales() {
		return this.pedimentosAduanales;
	}

	/**
	 * @deprecated
	 *
	public void setPedimentosAduanales(Set<PedimentoAduanal> pedimentosAduanales) {
		this.pedimentosAduanales = pedimentosAduanales;
	}
	*/
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<ValorCampoExtraComprobante> getComprobanteCamposExtra() {
		return comprobanteCamposExtra;
	}

	public void setComprobanteCamposExtra(
			Set<ValorCampoExtraComprobante> comprobanteCamposExtra) {
		this.comprobanteCamposExtra = comprobanteCamposExtra;
	}
/*
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<ComprobanteEtiqueta> getComprobanteEtiquetas() {
		return comprobanteEtiquetas;
	}

	public void setComprobanteEtiquetas(
			Set<ComprobanteEtiqueta> comprobanteEtiquetas) {
		this.comprobanteEtiquetas = comprobanteEtiquetas;
	}
	
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<ComprobanteFirma> getComprobanteFirmas() {
		return comprobanteFirmas;
	}

	public void setComprobanteFirmas(Set<ComprobanteFirma> comprobanteFirmas) {
		this.comprobanteFirmas = comprobanteFirmas;
	}
	*/
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<ComprobanteDescuento> getComprobanteDescuentos() {
		return comprobanteDescuento;
	}

	public void setComprobanteDescuentos(
			Set<ComprobanteDescuento> comprobanteDescuento) {
		this.comprobanteDescuento = comprobanteDescuento;
	}
	/*
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "comprobante")
	public Set<ComprobanteLeyenda> getComprobanteLeyendas() {
		return comprobanteLeyenda;
	}

	public void setComprobanteLeyendas(
			Set<ComprobanteLeyenda> comprobanteLeyenda) {
		this.comprobanteLeyenda = comprobanteLeyenda;
	}
	*/
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "comprobantePadre")
	public Set<Comprobante> getComprobantesHijos() {
		return comprobantesHijos;
	}
	
	public void setComprobantesHijos(Set<Comprobante> comprobantesHijos) {
		this.comprobantesHijos = comprobantesHijos;
	}

	@OneToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "id_carta_porte")
	public CartaPorte getCartaPorte() {
		return cartaPorte;
	}

	public void setCartaPorte(CartaPorte cartaPorte) {
		this.cartaPorte = cartaPorte;
	}

	@Column(name = "fecha_cancelacion")
	@Temporal(TemporalType.TIMESTAMP)
	public Calendar getFechaCancelacion() {
		return fechaCancelacion;
	}
	
	public void setFechaCancelacion(Calendar fechaCancelacion) {
		this.fechaCancelacion = fechaCancelacion;
	}
	/*
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "IDPERSONALIZACION")
	public Personalizacion getPersonalizacion() {
		return personalizacion;
	}

	public void setPersonalizacion(Personalizacion personalizacion) {
		this.personalizacion = personalizacion;
	}
	*/
	@OneToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "id_donataria", nullable = true)
	public Donataria getDonataria() {
		return donataria;
	}

	public void setDonataria(Donataria donataria) {
		this.donataria = donataria;
	}

	@Column(name="calculo")
	public Integer getCalculo() {
		return calculo;
	}

	public void setCalculo(Integer calculo) {
		this.calculo = calculo;
	}

	@Column(name="no_cuenta_pago", length = 255)
	public String getNumeroCuentaPago() {
		return numeroCuentaPago;
	}

	public void setNumeroCuentaPago(String numeroCuentaPago) {
		this.numeroCuentaPago = numeroCuentaPago;
	}
	
}